package cn.net.xinyi.xs.dao.hr.ibatis;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.orm.ObjectRetrievalFailureException;

import cn.net.xinyi.xs.dao.hr.UserDao;
import cn.net.xinyi.xs.dao.ibatis.BaseDaoiBatis;
import cn.net.xinyi.xs.dao.ibatis.iBatisDaoUtils;
import cn.net.xinyi.xs.model.hr.User;
import cn.net.xinyi.xs.model.system.Role;

/**
 * This class interacts with iBatis's SQL Maps to save and retrieve User related
 * objects.
 * 
 * @author <a href="mailto:caihualin2009@gmail.com">Cai Hua</a>
 */
public class UserDaoiBatis extends BaseDaoiBatis implements UserDao {

	/**
	 * Constructor that sets the entity to User.class.
	 */
	public UserDaoiBatis() {
		super();
	}

	/**
	 * Get user by id.
	 * 
	 * @param userId
	 *            the user's id
	 * @return a populated user object
	 */
	@SuppressWarnings("unchecked")
	public User get(Long userId) {
		User user = (User) getSqlMapClientTemplate().queryForObject(
				"getUserById", userId);

		if (user == null) {
			logger.warn("uh oh, user not found...");
			throw new ObjectRetrievalFailureException(User.class, userId);
		} else {
			List roles = getSqlMapClientTemplate().queryForList("getUserRoles",
					user);
			user.setRoles(roles);
		}

		return user;
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<User> getUsers() {
		List users = getSqlMapClientTemplate().queryForList("getUsers", null);

		// get the roles for each user
		for (int i = 0; i < users.size(); i++) {
			User user = (User) users.get(i);

			List roles = getSqlMapClientTemplate().queryForList("getUserRoles",
					user);
			user.setRoles(roles);
			users.set(i, user);
		}

		return users;
	}

	/**
	 * Convenience method to delete roles
	 * 
	 * @param userId
	 *            the id of the user to delete
	 */
	private void deleteUserRoles(final Long userId) {
		getSqlMapClientTemplate().update("deleteUserRoles", userId);
	}

	@SuppressWarnings("unchecked")
	private void addUserRoles(final User user) {
		if (user.getRoles() != null) {
			for (Role role : user.getRoles()) {
				Map<String, Long> newRole = new HashMap<String, Long>();
				newRole.put("userId", user.getId());
				newRole.put("roleId", role.getId());

				List<Role> userRoles = (List<Role>) getSqlMapClientTemplate()
						.queryForList("getUserRoles", user);
				if (userRoles.isEmpty()) {
					getSqlMapClientTemplate().update("addUserRole", newRole);
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public User saveUser(final User user) {
		iBatisDaoUtils.prepareObjectForSaveOrUpdate(user);

		if (user.getId() == null) {
			Long id = (Long) getSqlMapClientTemplate().insert("addUser", user);
			user.setId(id);
			addUserRoles(user);
		} else {
			getSqlMapClientTemplate().update("updateUser", user);
			deleteUserRoles(user.getId());
			addUserRoles(user);
		}
		return user;
	}

	/**
	 * {@inheritDoc}
	 */
	public void remove(Long userId) {
		deleteUserRoles(userId);
		getSqlMapClientTemplate().update("deleteUser", userId);
	}

	/**
	 * {@inheritDoc}
	 */
	public User getUserByUserName(String userName) {
		User user = (User) getSqlMapClientTemplate().queryForObject(
				"getUserByUserName", userName);
		return user;
	}

	/**
	 * {@inheritDoc}
	 */
	public String getUserPassword(String username) {
		return (String) getSqlMapClientTemplate().queryForObject(
				"getUserPassword", username);
	}
}
